package com.fzhucc.modules.expert.service.impl;

import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.expert.domain.Expert;
import com.fzhucc.modules.expert.domain.ExpertConsultationConfig;
import com.fzhucc.modules.expert.domain.ExpertOfflineConfig;
import com.fzhucc.modules.expert.domain.ExpertReservation;
import com.fzhucc.modules.expert.domain.dto.*;
import com.fzhucc.modules.expert.repository.ExpertConsultationConfigRepository;
import com.fzhucc.modules.expert.repository.ExpertOfflineConfigRepository;
import com.fzhucc.modules.expert.repository.ExpertRepository;
import com.fzhucc.modules.expert.repository.ExpertReservationRepository;
import com.fzhucc.modules.expert.service.ExpertReservationService;
import com.fzhucc.modules.expert.service.mapstruct.ExpertConsultationConfigMapper;
import com.fzhucc.modules.expert.service.mapstruct.ExpertMapper;
import com.fzhucc.modules.expert.service.mapstruct.ExpertOfflineConfigMapper;
import com.fzhucc.modules.expert.service.mapstruct.ExpertReservationMapper;
import com.fzhucc.modules.system.service.UserService;
import com.fzhucc.modules.system.service.dto.UserDto;
import com.fzhucc.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author yyg
 * @description 服务实现
 * @date 2023-10-20
 **/
@Service
@RequiredArgsConstructor
public class ExpertReservationServiceImpl implements ExpertReservationService {

    private final ExpertReservationRepository expertReservationRepository;
    private final ExpertReservationMapper expertReservationMapper;

    private final ExpertRepository expertRepository;

    private final ExpertConsultationConfigRepository expertConsultationConfigRepository;

    private final ExpertOfflineConfigRepository expertOfflineConfigRepository;

    private final ExpertMapper expertMapper;

    private final ExpertConsultationConfigMapper expertConsultationConfigMapper;

    private final ExpertOfflineConfigMapper expertOfflineConfigMapper;

    private final UserService userService;

    @Override
    public Map<String, Object> queryAll(ExpertReservationQueryCriteria criteria, Pageable pageable) {
        Page<ExpertReservation> page = expertReservationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ExpertReservationDto> map = page.map(expertReservationMapper::toDto);
        List<ExpertReservationDto> list = map.getContent();
        if (list != null && list.size() > 0) {
            for (ExpertReservationDto dto : list) {
                Integer expertId = dto.getExpertId();
                Optional<Expert> res = expertRepository.findById(expertId);
                if (res.isPresent()){
                    ExpertDto expertDto = expertMapper.toDto(res.get());
                    dto.setExpertDto(expertDto);
                }

                Integer expertConsultationId = dto.getExpertConsultationId();
                if (expertConsultationId!=null && expertConsultationId!=0){
                    Optional<ExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(expertConsultationId);
                    if (res2.isPresent()){
                        ExpertConsultationConfigDto expertConsultationConfigDto = expertConsultationConfigMapper.toDto(res2.get());
                        dto.setExpertConsultationConfigDto(expertConsultationConfigDto);
                    }
                }

                Integer expertOfflineId = dto.getExpertOfflineId();
                if (expertOfflineId!=null && expertOfflineId!=0){
                    Optional<ExpertOfflineConfig> res3 = expertOfflineConfigRepository.findById(expertOfflineId);
                    if (res3.isPresent()){
                        ExpertOfflineConfigDto expertOfflineConfigDto = expertOfflineConfigMapper.toDto(res3.get());
                        dto.setExpertOfflineConfigDto(expertOfflineConfigDto);
                    }
                }
            }
        }
        return PageUtil.toPage(map);
    }

    @Override
    public List<ExpertReservationDto> queryAll(ExpertReservationQueryCriteria criteria) {
        return expertReservationMapper.toDto(expertReservationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public ExpertReservationDto findById(Integer id) {
        ExpertReservation expertReservation = expertReservationRepository.findById(id).orElseGet(ExpertReservation::new);
        ValidationUtil.isNull(expertReservation.getId(), "ExpertReservation", "id", id);
        return expertReservationMapper.toDto(expertReservation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExpertReservationDto create(ExpertReservation resources) {
        return expertReservationMapper.toDto(expertReservationRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExpertReservationDto createByH5(ExpertReservationOrderDto dto) {
        ExpertReservation res = new ExpertReservation();
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        Integer expertId = dto.getExpertId();
        Optional<Expert> ops = expertRepository.findById(expertId);
        if (!ops.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        res.setExpertId(expertId);
        res.setDay(dto.getDay());
        res.setName(dto.getName());
        res.setPhone(dto.getPhone());
        Integer expertOfflineId = dto.getExpertOfflineId();
        Integer expertConsultationId = dto.getExpertConsultationId();
        res.setExpertOfflineId(expertOfflineId);
        res.setExpertConsultationId(expertConsultationId);
        res.setUnit(dto.getUnit());
        res.setUserId(userId);
        if (expertConsultationId != null && expertConsultationId != 0) {
            Optional<ExpertConsultationConfig> ops1 = expertConsultationConfigRepository.findById(expertConsultationId);
            if (!ops1.isPresent()) {
                throw new BadRequestException("专家线上咨询配置id未找到");
            }
            res.setType("线上咨询");
        } else if (expertOfflineId != null && expertOfflineId != 0) {
            Optional<ExpertOfflineConfig> ops2 = expertOfflineConfigRepository.findById(expertOfflineId);
            if (!ops2.isPresent()) {
                throw new BadRequestException("专家线下辅导配置id未找到");
            }
            res.setType("线下辅导");
        } else {
            res.setType("无");
        }

        UserDto userDto = userService.findById(userId);
        if (userDto.getIntegral() == null) {
            throw new BadRequestException("未找到用户积分");
        }
        Integer integral = userDto.getIntegral();//用户拥有的积分
        if (integral < 50) {
            throw new BadRequestException("积分不足");
        }
        int result_integral = integral - 50;
        userDto.setIntegral(result_integral);

        userService.updateIntegral(userId,result_integral);
        return expertReservationMapper.toDto(expertReservationRepository.save(res));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ExpertReservation resources) {
        ExpertReservation expertReservation = expertReservationRepository.findById(resources.getId()).orElseGet(ExpertReservation::new);
        ValidationUtil.isNull(expertReservation.getId(), "ExpertReservation", "id", resources.getId());
        expertReservation.copy(resources);
        expertReservationRepository.save(expertReservation);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            expertReservationRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<ExpertReservationDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExpertReservationDto expertReservation : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("预约人", expertReservation.getName());
            map.put("单位/学校", expertReservation.getUnit());
            map.put("手机号", expertReservation.getPhone());
            map.put("被预约专家id", expertReservation.getExpertId());
            map.put("日期", expertReservation.getDay());
            map.put("关联线上预约配置id  不为空说明关联了 线上预约", expertReservation.getExpertConsultationId());
            map.put("关联线下辅导配置id  不为空说明关联了 线下辅导", expertReservation.getExpertOfflineId());
            map.put("字典 专家预约类型 字典 expert_reservation_type", expertReservation.getType());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
